﻿using System;
using HK.Core.Common.Data;
using HK.Core.Common.Protocol;
using HK.Core.Common.Protocol.Data;
using HK.Core.GUIEx.Attribute;
using HK.Core.GUIEx.Protocol.Attribute;
using HK.Core.Serializable.Attribute;
using HK.Core.Settings.Protocol;
using UnityEngine;

namespace HK.Core.Settings.Data
{
    /// <summary>
    /// 下载设定信息
    /// </summary>
    [Serializable]
    public sealed class DownloadSettingsData : JsonData<DownloadSettingsData>, IDownloadSettingsData
    {

#region Create

        /// <summary>
        /// 创建下载设定信息
        /// </summary>
        /// <param name="iUrl">下载路径</param>
        /// <param name="iThreaderNum">线程上线数(默认:5)</param>
        /// <returns>下载设定信息</returns>
        public static DownloadSettingsData Create(string iUrl = null, int iThreaderNum = 5)
        {
            return new DownloadSettingsData
            {
                url = iUrl, threaderNum = iThreaderNum
            };
        }

#endregion
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        private DownloadSettingsData() {}
        
        
        [SerializeField, GenericField("下载地址", null, "下载服务器基本信息的地址，并非资源的的直接下载地址")]
        private string url = null;
        /// <summary>
        /// 下载地址
        /// </summary>
        public string Url
        {
            get => url;
            private set => url = value;
        }
        
        [SerializeField, GenericField("备用地址", null, "通过下载地址下载失败后，会转向此地址下载相关信息。")]
        private string bakUrl = null;
        /// <summary>
        /// 备用下载地址
        /// </summary>
        public string BakUrl 
        {
            get => bakUrl;
            private set => bakUrl = value;
        }

        [SerializeField, IntSlideMinMax("线程上限数", 3, 10, "取值范围：3～10.")]
        private int threaderNum = 5;
        /// <summary>
        /// 现在线程数
        /// </summary>
        public int ThreaderNum 
        {
            get => threaderNum;
            private set => threaderNum = value;
        }
        
        [SerializeField, IntSlideMinMax("重试", 3, 10, "下载失败重试次数。取值范围：3～10.")]
        private int retry = 3;
        /// <summary>
        /// 重试次数
        /// </summary>
        public int Retry
        {
            get => retry;
            private set => retry = value;
        }
        
        [SerializeField, GenericField("断点续载", null, "是否开启允许断点续载。默认：开启。")]
        private bool brokenDownload = true;
        /// <summary>
        /// 断点续载标志位
        /// </summary>
        public bool BrokenDownload 
        {
            get => background;
            private set => background = value;
        }
        
        [SerializeField, GenericField("后台下载", null, "是否开启允许后台下载。默认：开启。注意：需要获得系统级别的权限，iOS需要OC代码的重新，Android需要Java端的重新，咱不支持。")]
        private bool background = true;
        /// <summary>
        /// 后台下载标志位
        /// </summary>
        public bool Background 
        {
            get => background;
            private set => background = value;
        }

        [SerializeField, IntSlideMinMax("下载缓存", 1024, 4096, "每一次下载写入缓存大小。单位:Byte; 默认:2048。取值范围：1024～4096。建议设定为2的N次幂。")]
        private int buffer = 2048;
        /// <summary>
        /// 下载缓存
        /// <para>* 单位 : Byte</para>
        /// </summary>
        public int Buffer 
        {
            get => buffer;
            private set => buffer = value;
        }

        [SerializeField, GenericField("下载完成", null, "资源是否下载完成", (int)GUIOperateOptions.ReadOnlyGenericField)]
        private bool downloaded = false;
        /// <summary>
        /// 下载完成标志位
        /// </summary>
        public bool Downloaded 
        {
            get => downloaded;
            set => downloaded = value;
        }

        /// <summary>
        /// 有效标志位
        /// </summary>
        public override bool Valid => !string.IsNullOrEmpty(url);

        /// <summary>
        /// 应用数据
        /// </summary>
        /// <param name="iData">数据</param>
        /// <param name="iImport">导入标志位(true:从相应的*.json文件导入; false:反之;)</param>
        /// <returns>true:有变更; false:无变更;</returns>
        public override bool ApplyData(IJsonData iData, bool iImport = false)
        {
            if (null == iData || !iData.Valid) return false;
            var dirty = base.ApplyData(iData, iImport);
            if (dirty && !iImport)
            {
                Dirty = true;
            }

            if (iData is IDownloadSettingsData settings)
            {
                url = UpdateValue(url, settings.Url, iImport);
                bakUrl = UpdateValue(bakUrl, settings.BakUrl, iImport);
                threaderNum = UpdateValue(threaderNum, settings.ThreaderNum, iImport);
                brokenDownload = UpdateValue(brokenDownload, settings.BrokenDownload, iImport);
                background = UpdateValue(background, settings.Background, iImport);
                buffer = UpdateValue(buffer, settings.Buffer, iImport);
                downloaded = UpdateValue(downloaded, settings.Downloaded, iImport);
            }

            return Dirty;
        }
        
        /// <summary>
        /// 清空
        /// </summary>
        public override void Clear()
        {
            base.Clear();

            url = null;
            bakUrl = null;
            threaderNum = 5;
            brokenDownload = true;
            background = true;
            buffer = 2048;
            downloaded = false;
        }
    }
}
